package com.example.springbootdemo.utils.elasticsearch;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.example.springbootdemo.utils.PageUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.AnalyzeRequest;
import org.elasticsearch.client.indices.AnalyzeResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.GeoDistanceQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.reindex.DeleteByQueryRequest;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.*;


/**
 * Elasticsearch 工具类
 *
 * @author wuzhen on 2021/1/19
 */
@Component
@Slf4j
public class ElasticsearchUtil<T> {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    final Type type = new TypeReference<T>() {
    }.getType();

    /**
     * 创建索引
     *
     * @param index 要创建的索引的名字.
     * @return 创建索引的响应对象。可以使用 {@link CreateIndexResponse#isAcknowledged()} 来判断是否创建成功。
     */
    public boolean createIndex(String index) throws IOException {
        if (isIndexExist(index)) {
            log.error("索引已经存在!");
            return false;
        }
        CreateIndexRequest request = new CreateIndexRequest(index);
        CreateIndexResponse response = restHighLevelClient.indices()
                .create(request, RequestOptions.DEFAULT);
        return response.isAcknowledged();
    }

    /**
     * 判断索引是否存在
     *
     * @param index 要判断是否存在的索引的名字
     * @return 返回是否存在。
     * <ul>
     * 	<li>true:存在</li>
     * 	<li>false:不存在</li>
     * </ul>
     */
    public boolean isIndexExist(String index) throws IOException {
        GetIndexRequest request = new GetIndexRequest(index);
        boolean exists;
        try {
            exists = restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            log.error("{}", e.getMessage(), e);
            return false;
        }
        return exists;
    }

    /**
     * 删除索引
     *
     * @param index 要删除的索引的名字
     * @return 索引的响应对象。可以使用 {@link CreateIndexResponse#isAcknowledged()} 来判断是否创建成功。
     */
    public boolean deleteIndex(String index) throws IOException {
        if (!isIndexExist(index)) {
            log.error("索引不存在!");
            return false;
        }
        DeleteIndexRequest request = new DeleteIndexRequest(index);
        AcknowledgedResponse delete = restHighLevelClient.indices()
                .delete(request, RequestOptions.DEFAULT);
        return delete.isAcknowledged();
    }

    /**
     * 数据添加，自定义id
     *
     * @param t     要增加的数据
     * @param index 索引，类似数据库
     * @param id    数据ID,为null时es随机生成
     * @return 创建结果。如果 {@link IndexResponse#getId()} 不为null、且id长度大于0，那么就成功了
     */
    public String addData(T t, String index, String id) throws IOException {
        //创建请求
        IndexRequest request = new IndexRequest(index);
        //规则 put /test_index/_doc/1
        request.id(id);
        request.timeout(TimeValue.timeValueSeconds(1));
        //将数据放入请求 json
        IndexRequest source = request.source(JSON.toJSONString(t), XContentType.JSON);
        //客户端发送请求
        IndexResponse response = restHighLevelClient.index(request, RequestOptions.DEFAULT);
        return response.getId();
    }

    /**
     * 数据添加 随机id
     *
     * @param t     要增加的数据
     * @param index 索引，类似数据库
     * @return 创建结果。如果 {@link IndexResponse#getId()} 不为null、且id长度大于0，那么就成功了
     */
    public String addData(T t, String index) throws IOException {
        return addData(t, index, UUID.randomUUID().toString().replaceAll("-", "").toUpperCase());
    }

    /**
     * 通过ID删除数据
     *
     * @param index 索引，类似数据库
     * @param id    数据ID
     */
    public void deleteDataById(String index, String id) throws IOException {
        DeleteRequest request = new DeleteRequest(index, id);
        request.timeout(TimeValue.timeValueSeconds(1));
        restHighLevelClient.delete(request, RequestOptions.DEFAULT);
    }

    /**
     * 通过ID 更新数据
     *
     * @param t     要更新数据
     * @param index 索引，类似数据库
     * @param id    数据ID
     */
    public void updateDataById(T t, String index, String id) throws IOException {
        UpdateRequest update = new UpdateRequest(index, id);
        update.timeout(TimeValue.timeValueSeconds(1));
        update.doc(JSON.toJSONString(t), XContentType.JSON);
        restHighLevelClient.update(update, RequestOptions.DEFAULT);
    }

    /**
     * 通过ID获取数据
     *
     * @param index  索引，类似数据库
     * @param id     数据ID
     * @param fields 需要显示的字段，逗号分隔（缺省为全部字段）
     * @return 数据集
     */
    public Map<String, Object> searchDataById(String index, String id, String fields) throws IOException {
        GetRequest request = new GetRequest(index, id);
        if (StringUtils.isNotEmpty(fields)) {
            //只查询特定字段。如果需要查询所有字段则不设置该项。
            //new FetchSourceContext 参数的意思是 是否携带source,包含的字段,排除的字段
            request.fetchSourceContext(new FetchSourceContext(true, fields.split(","), Strings.EMPTY_ARRAY));
        }
        GetResponse response = restHighLevelClient.get(request, RequestOptions.DEFAULT);
        return response.getSource();
    }

    /**
     * 通过ID判断文档是否存在
     *
     * @param index 索引，类似数据库
     * @param id    数据ID
     * @return <ul>
     * 			<li>true:存在</li>
     * 			<li>false:不存在</li>
     * 		</ul>
     */
    public boolean existsById(String index, String id) throws IOException {
        GetRequest request = new GetRequest(index, id);
        //不获取返回的_source的上下文
        request.fetchSourceContext(new FetchSourceContext(false));
        //是否需要排序
        request.storedFields("_none_");
        return restHighLevelClient.exists(request, RequestOptions.DEFAULT);
    }

    /**
     * @param index   索引，类似数据库
     * @param objects 数据
     * @return <ul>
     * 			<li>true:成功</li>
     * 			<li>false:不成功</li>
     * 		</ul>
     */
    public boolean bulkPost(String index, List<? extends T> objects) {
        BulkRequest bulkRequest = new BulkRequest();
        BulkResponse response = null;
        for (Object object : objects) {
            IndexRequest request = new IndexRequest(index);
            request.source(JSON.toJSONString(object), XContentType.JSON);
            bulkRequest.add(request);
        }
        try {
            response = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            log.error("{}", e.getMessage(), e);
            return false;
        }
        //是否有失败，返回false 代表成功
        return !response.hasFailures();
    }

    /**
     * 根据经纬度查询范围查找location 经纬度字段，distance 距离中心范围KM，lat  lon 圆心经纬度
     *
     * @param index
     * @param longitude
     * @param latitude
     * @param distance
     * @return
     */
    public SearchResponse geoDistanceQuery(String index, Float longitude, Float latitude, String distance) throws IOException {

        if (longitude == null || latitude == null) {
            return null;
        }
        //拼接条件
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
//        QueryBuilder isdeleteBuilder = QueryBuilders.termQuery("isdelete", false);
        // 以某点为中心，搜索指定范围
        GeoDistanceQueryBuilder distanceQueryBuilder = new GeoDistanceQueryBuilder("location");
        distanceQueryBuilder.point(latitude, longitude);
        //查询单位：km
        distanceQueryBuilder.distance(distance, DistanceUnit.KILOMETERS);
        boolQueryBuilder.filter(distanceQueryBuilder);
//        boolQueryBuilder.must(isdeleteBuilder);

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(boolQueryBuilder);

        SearchRequest searchRequest = new SearchRequest(index);
        searchRequest.source(searchSourceBuilder);

        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        return searchResponse;
    }

    /**
     * 获取低水平客户端
     *
     * @return
     */
    public RestClient getLowLevelClient() {
        return restHighLevelClient.getLowLevelClient();
    }

    /**
     * 高亮结果集 特殊处理
     * map转对象 JSONObject.parseObject(JSONObject.toJSONString(map), Content.class)
     *
     * @param searchResponse
     * @param highlightField
     */
    private List<Map<String, Object>> setSearchResponse(SearchResponse searchResponse, String highlightField) {
        //解析结果
        ArrayList<Map<String, Object>> list = new ArrayList<>();
        for (SearchHit hit : searchResponse.getHits().getHits()) {
            Map<String, HighlightField> high = hit.getHighlightFields();
            HighlightField title = high.get(highlightField);
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();//原来的结果
            //解析高亮字段,将原来的字段换为高亮字段
            if (title != null) {
                Text[] texts = title.fragments();
                String nTitle = "";
                for (Text text : texts) {
                    nTitle += text;
                }
                //替换
                sourceAsMap.put(highlightField, nTitle);
            }
            list.add(sourceAsMap);
        }
        return list;
    }

    /**
     * 查询并分页
     *
     * @param index          索引名称
     * @param query          查询条件
     * @param size           文档大小限制
     * @param fields         需要显示的字段，逗号分隔（缺省为全部字段）
     * @param sortField      排序字段
     * @param highlightField 高亮字段
     * @return
     */
    public List<Map<String, Object>> searchListData(String index,
                                                    SearchSourceBuilder query,
                                                    Integer size,
                                                    Integer from,
                                                    String fields,
                                                    String sortField,
                                                    String highlightField) throws IOException {
        SearchRequest request = new SearchRequest(index);
        SearchSourceBuilder builder = query;
        if (StringUtils.isNotEmpty(fields)) {
            //只查询特定字段。如果需要查询所有字段则不设置该项。
            builder.fetchSource(new FetchSourceContext(true, fields.split(","), Strings.EMPTY_ARRAY));
        }
        from = from <= 0 ? 0 : from * size;
        //设置确定结果要从哪个索引开始搜索的from选项，默认为0
        builder.from(from);
        builder.size(size);
        if (StringUtils.isNotEmpty(sortField)) {
            //排序字段，注意如果proposal_no是text类型会默认带有keyword性质，需要拼接.keyword
            builder.sort(sortField + ".keyword", SortOrder.ASC);
        }
        //高亮
        HighlightBuilder highlight = new HighlightBuilder();
        highlight.field(highlightField);
        //关闭多个高亮
        highlight.requireFieldMatch(false);
        highlight.preTags("<span style='color:red'>");
        highlight.postTags("</span>");
        builder.highlighter(highlight);
        //不返回源数据。只有条数之类的数据。
//        builder.fetchSource(false);
        request.source(builder);
        SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
        log.error("==" + response.getHits().getTotalHits());
        if (response.status().getStatus() == 200) {
            // 解析对象
            return setSearchResponse(response, highlightField);
        }
        return null;
    }

    /**
     * @param searchIndex   索引名
     * @param searchField   索引字段
     * @param searchContent 文字内容
     * @return 分词结果
     */
    public List<String> getIkAnalyzeSearchTerms(String searchIndex, String searchField, String... searchContent) {

        AnalyzeRequest analyzeRequest = AnalyzeRequest.withField(searchIndex, searchField, searchContent);

        List<String> list = new LinkedList<>();
        try {
            AnalyzeResponse analyzeResponse = restHighLevelClient.indices().analyze(analyzeRequest, RequestOptions.DEFAULT);
            List<AnalyzeResponse.AnalyzeToken> tokens = analyzeResponse.getTokens(); // 获取所有分词的内容
            // 使用Java 8 语法获取分词内容
            tokens.forEach(token -> {
                // 过滤内容，如果文字小于2位也过滤掉
                if (!"<NUM>".equals(token.getType()) || token.getTerm().length() > 2) {
                    String term = token.getTerm(); // 分词内容
                    list.add(term);
                }
            });

        } catch (IOException e) {
            log.error("{}", e.getMessage(), e);
        }
        return list;
    }

    /**
     * 数据添加，向elasticsearch 中添加一条数据
     *
     * @param params    要增加的数据，key-value形式。 其中map.value 支持的类型有 String、int、long、float、double、boolean
     * @param indexName 索引名字，类似数据库的表，是添加进那个表
     * @param id        要添加的这条数据的id, 如果传入null，则由es系统自动生成一个唯一ID
     * @return 创建结果。如果 {@link IndexResponse#getId()} 不为null、且id长度大于0，那么就成功了
     */
    public IndexResponse put(T params, String indexName, String id) {
        //创建请求
        IndexRequest request = new IndexRequest(indexName);
        if (id != null) {
            request.id(id);
        }
        request.timeout(TimeValue.timeValueSeconds(5));

        IndexResponse response = null;
        try {

            response = restHighLevelClient.index(request.source(JSON.toJSONString(params), XContentType.JSON), RequestOptions.DEFAULT);
        } catch (IOException e) {
            log.error("{}", e.getMessage(), e);
        }
        return response;
    }

    /**
     * 数据添加，向elasticsearch 中添加一条数据
     *
     * @param params    要增加的数据，key-value形式。 其中map.value 支持的类型有 String、int、long、float、double、boolean
     * @param indexName 索引名字，类似数据库的表，是添加进那个表
     * @return 创建结果。如果 {@link IndexResponse#getId()} 不为null、且id长度大于0，那么就成功了
     */
    public IndexResponse put(T params, String indexName) {
        return put(params, indexName, null);
    }

    /**
     * 批量添加数据
     *
     * @param list      批量添加的数据的List
     * @param indexName 索引名字，类似数据库的表，是添加进那个表
     * @return {@link BulkResponse}
     */
    public BulkResponse puts(List<T> list, String indexName) {
        //批量增加
        BulkRequest bulkAddRequest = new BulkRequest();
        IndexRequest indexRequest;
        for (T t : list) {
            indexRequest = new IndexRequest(indexName);
            indexRequest.source(JSON.toJSONString(t), XContentType.JSON);
            bulkAddRequest.add(indexRequest);
        }

        BulkResponse bulkAddResponse = null;
        try {
            bulkAddResponse = restHighLevelClient.bulk(bulkAddRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            log.error("{}", e.getMessage(), e);
        }
        return bulkAddResponse;
    }

    /**
     * 查询并分页
     *
     * @param indexName 索引名字
     * @param query     查询条件， {@link SearchSourceBuilder}
     * @param from      从第几条开始查询，相当于 limit a,b 中的a ，比如要从最开始第一条查，可传入： 0
     * @param size      本次查询最大查询出多少条数据 ,相当于 limit a,b 中的b
     * @return {@link SearchResponse} 结果，可以通过 response.status().getStatus() == 200 来判断是否执行成功
     */
    public SearchResponse search(String indexName, SearchSourceBuilder query, Integer from, Integer size) {
        SearchRequest request = new SearchRequest(indexName);
        query.from(from);
        query.size(size);
        request.source(query);
        SearchResponse response = null;
        try {
            response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            log.error("{}", e.getMessage(), e);
        }
        return response;
    }

    /**
     * 查询并分页
     *
     * @param indexName 索引名字
     * @param query     查询条件， {@link SearchSourceBuilder}
     * @param from      从第几条开始查询，相当于 limit a,b 中的a ，比如要从最开始第一条查，可传入： 0
     * @param size      本次查询最大查询出多少条数据 ,相当于 limit a,b 中的b
     * @return {@link SearchResponse} 结果，可以通过 response.status().getStatus() == 200 来判断是否执行成功
     */
    public SearchResponse boostSearch(String indexName, SearchSourceBuilder query, Integer from, Integer size) {
        SearchRequest request = new SearchRequest(indexName);
        query.from(from);
        query.size(size);
        request.source(query);
        SearchResponse response = null;
        try {
            response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            log.error("{}", e.getMessage(), e);
        }
        return response;
    }

    /**
     * 查询数据
     *
     * @param indexName   索引名字
     * @param queryString 查询条件，传入如： name:guanleiming AND age:123
     * @param from        从第几条开始查询，相当于 limit a,b 中的a ，比如要从最开始第一条查，可传入： 0
     * @param size        本次查询最大查询出多少条数据 ,相当于 limit a,b 中的b
     * @param sort        排序方式。如果不需要排序，传入null即可。 比如要根据加入时间time由大到小，传入的便是： SortBuilders.fieldSort("time").order(SortOrder.DESC)
     * @return 查询的结果，封装成list返回。list中的每条都是一条结果。如果链接es出错或者查询异常又或者什么都没查出，那么都是返回一个 new ArrayList<Map<String,Object>>(); ，任何情况返回值不会为null
     * <p>返回的结果集中，每条会自动加入一项 esid ，这个是在es中本条记录的唯一id编号，es自动赋予的。</p>
     */
    public List<Map<String, Object>> search(String indexName, String queryString, Integer from, Integer size, SortBuilder sort) {
        List<Map<String, Object>> list = new ArrayList<>();

        QueryBuilder queryBuilder = QueryBuilders.queryStringQuery(queryString);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(queryBuilder);
        //判断是否使用排序
        if (sort != null) {
            searchSourceBuilder.sort(sort);
        }
        SearchResponse response = search(indexName, searchSourceBuilder, from, size);
        if (response.status().getStatus() == 200) {
            SearchHit[] shs = response.getHits().getHits();
            for (SearchHit sh : shs) {
                Map<String, Object> map = sh.getSourceAsMap();
                list.add(map);
            }
        }

        return list;
    }

    /**
     * 查询数据
     * <p>如果数据超过100条，那么只会返回前100条数据。<p>
     *
     * @param indexName   索引名字
     * @param queryString 查询条件，传入如： name:guanleiming AND age:123
     * @return 查询的结果，封装成list返回。list中的每条都是一条结果。如果链接es出错或者查询异常又或者什么都没查出，那么都是返回一个 new ArrayList<Map<String,Object>>(); ，任何情况返回值不会为null
     * <p>返回的结果集中，每条会自动加入一项 esid ，这个是在es中本条记录的唯一id编号，es自动赋予的。</p>
     */
    public List<Map<String, Object>> search(String indexName, String queryString) {
        return search(indexName, queryString, 0, 100, null);
    }

    /**
     * 查询数据 分页
     *
     * @param indexName    索引名字
     * @param queryBuilder 条件构造器
     * @param from         从第几条开始查询，相当于 limit a,b 中的a ，比如要从最开始第一条查，可传入： 0
     * @param size         本次查询最大查询出多少条数据 ,相当于 limit a,b 中的b
     * @param sort         排序方式。如果不需要排序，传入null即可。 比如要根据加入时间time由大到小，传入的便是： SortBuilders.fieldSort("time").order(SortOrder.DESC)
     * @return 查询的结果，封装成list返回。list中的每条都是一条结果。如果链接es出错或者查询异常又或者什么都没查出，那么都是返回一个 new ArrayList<Map<String,Object>>(); ，任何情况返回值不会为null
     */
    public List<Map<String, Object>> search(String indexName, QueryBuilder queryBuilder, Integer from, Integer size, SortBuilder sort) {
        List<Map<String, Object>> list = new ArrayList<>();

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(queryBuilder);
        //判断是否使用排序
        if (sort != null) {
            searchSourceBuilder.sort(sort);
        }
        SearchResponse response = search(indexName, searchSourceBuilder, from, size);
        if (response.status().getStatus() == 200) {
            SearchHit[] shs = response.getHits().getHits();
            for (SearchHit sh : shs) {
                Map<String, Object> map = sh.getSourceAsMap();
                list.add(map);
            }
        }
        return list;
    }

    /**
     * 查询数据 分页
     *
     * @param indexName    索引名字
     * @param queryBuilder 条件构造器
     * @param page         现在页数
     * @param limit        一页显示的条数
     * @return 查询的结果，封装成list返回。list中的每条都是一条结果。如果链接es出错或者查询异常又或者什么都没查出，那么都是返回一个 new ArrayList<Map<String,Object>>(); ，任何情况返回值不会为null
     */
    public PageUtils<Map<String, Object>> search(String indexName, QueryBuilder queryBuilder, Integer page, Integer limit) {

        List<Map<String, Object>> list = new ArrayList<>();

        PageUtils<Map<String, Object>> mapPageUtils = new PageUtils<>(list, 0, limit, page);

        //page必须大于或等于1
        if (page < 1) {
            return mapPageUtils;
        }
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(queryBuilder);

        //从第几条内容开始
        int from = (page - 1) * limit;
        SearchResponse response = search(indexName, searchSourceBuilder, from, limit);
        if (response.status().getStatus() == 200) {
            SearchHit[] shs = response.getHits().getHits();

            for (SearchHit sh : shs) {
                Map<String, Object> map = sh.getSourceAsMap();
                list.add(map);
            }
            //分页计算
            long total = response.getHits().getTotalHits().value;


            mapPageUtils = new PageUtils<>(list, (int) total, limit, page);
        }
        return mapPageUtils;
    }

    /**
     * 查询数据
     * <p>如果数据超过100条，那么只会返回前100条数据。<p>
     *
     * @param indexName    索引名字
     * @param queryBuilder 条件构造器
     * @return 查询的结果，封装成list返回。list中的每条都是一条结果。如果链接es出错或者查询异常又或者什么都没查出，那么都是返回一个 new ArrayList<Map<String,Object>>(); ，任何情况返回值不会为null
     * <p>返回的结果集中，每条会自动加入一项 esid ，这个是在es中本条记录的唯一id编号，es自动赋予的。</p>
     */
    public List<Map<String, Object>> search(String indexName, QueryBuilder queryBuilder) {
        return search(indexName, queryBuilder, 0, 100, null);
    }

    public void delete(String indexName, QueryBuilder queryBuilder) {
        DeleteByQueryRequest request = new DeleteByQueryRequest(indexName);

        request.setQuery(queryBuilder);
        try {
            restHighLevelClient.deleteByQuery(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            log.error("删除失败{}", e.getMessage(), e);
        }
    }


}

